package com.lzh.stack;

/**
 * @author liuzhihao
 * @create 2021-10-15 21:50
 * 使用栈实现计算器功能（输入一个运算式）
 */
public class CalculatorStackDemo {

    public static void main(String[] args) {
        String expression = "3+4*3-5"; // 计算表达式

        StackArr numStack = new StackArr(10); // 数栈
        StackArr operStack = new StackArr(10); // 运算符栈

        char ch = ' '; // 记录表达式的第几位
        int num1; // 出栈的第一个数
        int num2; // 出栈的第二个数
        int index = 0; // 索引，用来遍历表达式
        int oper;
        int res = 0;
        String keepNum = "";
        while (true) {
            ch = expression.substring(index, index + 1).charAt(0); //
            if (operStack.isOper(ch)) { // 如果是运算符
                if (!operStack.isEmpty()) {
                    if (operStack.priority(ch) <= operStack.priority(operStack.peak())) {
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                        oper = operStack.pop();
                        res = numStack.cal(num1, num2, oper);
                        operStack.push(ch);
                        numStack.push(res);
                    } else {
                        operStack.push(ch);
                    }
                } else {
                    operStack.push(ch);
                }
            } else { // 如果是数
//                numStack.push(ch - 48);
                keepNum += ch;

                if (index == expression.length() - 1) {
                    numStack.push(Integer.parseInt(keepNum));
                } else {
                    if (operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
                        numStack.push(Integer.parseInt(keepNum));
                        keepNum = "";
                    }
                }
            }
            index++;
            if (index >= expression.length()){
                break;
            }
        }

        while(true) {
            if (operStack.isEmpty()) {
                break;
            }
            num1 = numStack.pop();
            num2 = numStack.pop();
            oper = operStack.pop();
            res = numStack.cal(num1, num2, oper);
            numStack.push(res);
        }
        System.out.printf("%s = %d", expression, res);
    }
}

class StackArr {
    int[] arr;
    int top;
    int maxSize;

    public StackArr(int maxSize) {
        this.maxSize = maxSize;
        arr = new int[maxSize];
        top = -1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public boolean isFull() {
        return top == maxSize - 1;
    }

    public void push(int num) {
        if (isFull()) {
            System.out.println("栈满，无法入栈");
            return;
        }
        top++;
        arr[top] = num;
    }

    public boolean isOper(int ch) {
        return ch == '+' || ch == '-' || ch == '*' || ch == '/';
    }

    public int cal(int num1, int num2, int oper){
        int res = 0;
        switch (oper) {
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num2 - num1;
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }

    public int priority(int ch) {
        if (ch == '+' || ch == '-') {
            return 0;
        } else if (ch == '*' || ch == '/') {
            return 1;
        } else {
            return -1;
        }
    }

    public int peak() {
        return arr[top];
    }

    public int pop() {
        if (isEmpty()) {
            System.out.println("栈空，不能出栈");
            throw new RuntimeException("栈空，不能出栈");
        }
        int value = arr[top];
        top--;
        return value;
    }

}

